# -*- coding:utf-8 -*-
from django.shortcuts import render
from toolkit.pre_load import pre_load_thu
from toolkit.pre_load import neo_con
from Model.neo_models import Neo4j
from demo import SVMModel
from demo import BILSTM_CRF
from fuzzywuzzy import process

import random
import re

thu_lac = pre_load_thu
db = neo_con


# 1.Phe_has_Cause
# 2.Phe_has_Mnt
# 3.Cause_lead_Phe
# 4.Mnt_to_Phe
# 5.Mnt_has_Cause

# 1.根据故障现象进行模糊查询故障原因 Phe_has_Cause , return ret_dict
def getCauseByPhe(phe, ret_dict):
    answer = db.getCauseByPhe(phe)
    print("answer-getCauseByPhe:" + str(len(answer)))
    if len(answer) > 0:
        # 结果数大于6则随机取6个
        if len(answer) > 6:
            selected_index = []
            n = len(answer)
            m = 6
            for i in range(n):
                rand = random.randint(0, n - i - 1)
                if rand < m:
                    m -= 1
                    selected_index.append(i)
        else:
            selected_index = [i for i in range(len(answer))]
        for index in selected_index:
            cause = answer[index]['n2']['title']
            if (ret_dict.get('list') is None):
                ret_dict['list'] = [
                    {'entity1': phe, 'rel': '有原因', 'entity2': cause, 'entity1_type': '故障现象', 'entity2_type': '故障原因'}]
            else:
                ret_dict['list'].append(
                    {'entity1': phe, 'rel': '有原因', 'entity2': cause, 'entity1_type': '故障现象', 'entity2_type': '故障原因'})

            if (ret_dict.get('answer') is None):
                ret_dict['answer'] = [cause]
            else:
                ret_dict['answer'].append(cause)
    # 将所有的故障原因作为answer返回
    return ret_dict


# 2.根据故障现象查询维护措施 Phe_has_Mnt
def getMntByPhe(phe, ret_dict):
    answer = db.getMntByPhe(phe)
    print("answer-getMntByPhe:" + str(len(answer)))
    if (len(answer) > 0):
        # 结果数大于6则随机取6个
        if len(answer) > 6:
            selected_index = []
            n = len(answer)
            m = 6
            for i in range(n):
                rand = random.randint(0, n - i - 1)
                if rand < m:
                    m -= 1
                    selected_index.append(i)
        else:
            selected_index = [i for i in range(len(answer))]
        for index in selected_index:
            mnt = answer[index]['n2']['title']
            if (ret_dict.get('list') is None):
                ret_dict['list'] = [
                    {'entity1': phe, 'rel': '对应维护措施', 'entity2': mnt, 'entity1_type': '故障现象', 'entity2_type': '故障维护措施'}]
            else:
                ret_dict['list'].append(
                    {'entity1': phe, 'rel': '对应维护措施', 'entity2': mnt, 'entity1_type': '故障现象', 'entity2_type': '故障维护措施'})

            if (ret_dict.get('answer') is None):
                ret_dict['answer'] = [mnt]
            else:
                ret_dict['answer'].append(mnt)
        # 将所有的故障维护措施作为answer返回
    return ret_dict


# 3.根据故障原因查找可能导致的故障现象 Cause_lead_Phe
def getPheByCause(cau, ret_dict):
    answer = db.getPheByCause(cau)
    print("answer-getPheByCause:" + str(len(answer)))
    if len(answer) > 0:
        # 结果数大于6则随机取6个
        if len(answer) > 6:
            selected_index = []
            n = len(answer)
            m = 6
            for i in range(n):
                rand = random.randint(0, n - i - 1)
                if rand < m:
                    m -= 1
                    selected_index.append(i)
        else:
            selected_index = [i for i in range(len(answer))]
        for index in selected_index:
            phe = answer[index]['n2']['title']
            if (ret_dict.get('list') is None):
                ret_dict['list'] = [
                    {'entity1': cau, 'rel': '导致', 'entity2': phe, 'entity1_type': '故障原因', 'entity2_type': '故障现象'}]
            else:
                ret_dict['list'].append(
                    {'entity1': cau, 'rel': '导致', 'entity2': phe, 'entity1_type': '故障原因', 'entity2_type': '故障现象'})

            if (ret_dict.get('answer') is None):
                ret_dict['answer'] = [phe]
            else:
                ret_dict['answer'].append(phe)
    # 将所有的故障现象作为answer返回
    return ret_dict


# 4.根据维护方法找可以解决的故障现象 Mnt_to_Phe
def getPheByMnt(mnt, ret_dict):
    answer = db.getPheByMnt(mnt)
    print("answer-getPheByMnt:" + str(len(answer)))
    if len(answer) > 0:
        # 结果数大于6则随机取6个
        if len(answer) > 6:
            selected_index = []
            n = len(answer)
            m = 6
            for i in range(n):
                rand = random.randint(0, n - i - 1)
                if rand < m:
                    m -= 1
                    selected_index.append(i)
        else:
            selected_index = [i for i in range(len(answer))]
        for index in selected_index:
            phe = answer[index]['n2']['title']
            if (ret_dict.get('list') is None):
                ret_dict['list'] = [
                    {'entity1': mnt, 'rel': '可维护', 'entity2': phe, 'entity1_type': '故障维护措施', 'entity2_type': '故障现象'}]
            else:
                ret_dict['list'].append(
                    {'entity1': mnt, 'rel': '可维护', 'entity2': phe, 'entity1_type': '故障维护措施', 'entity2_type': '故障现象'})

            if (ret_dict.get('answer') is None):
                ret_dict['answer'] = [phe]
            else:
                ret_dict['answer'].append(phe)
    # 将所有的故障原因作为answer返回
    return ret_dict


# 5.根据故障维护方法找可以针对的故障原因  Mnt_has_Cause
def getCauseByMnt(mnt, ret_dict):
    print("根据维护方法获得原因mnt:" + mnt)
    answer = db.getCauseByMnt(mnt)
    print("answer-getCauseByMnt:" + str(len(answer)))
    if len(answer) > 0:
        # 结果数大于6则随机取6个
        if len(answer) > 6:
            selected_index = []
            n = len(answer)
            m = 6
            for i in range(n):
                rand = random.randint(0, n - i - 1)
                if rand < m:
                    m -= 1
                    selected_index.append(i)
        else:
            selected_index = [i for i in range(len(answer))]
        for index in selected_index:
            cause = answer[index]['n2']['title']
            if (ret_dict.get('list') is None):
                ret_dict['list'] = [
                    {'entity1': mnt, 'rel': '可针对', 'entity2': cause, 'entity1_type': '故障维护措施', 'entity2_type': '故障原因'}]
            else:
                ret_dict['list'].append(
                    {'entity1': mnt, 'rel': '可针对', 'entity2': cause, 'entity1_type': '故障维护措施', 'entity2_type': '故障原因'})

            if (ret_dict.get('answer') is None):
                ret_dict['answer'] = [cause]
            else:
                ret_dict['answer'].append(cause)
    # 将所有的故障原因作为answer返回
    return ret_dict


# 将识别出来的实体和问题类型结合，到图谱中找到对应的最相似的实体，并将最终的实体与问题类型结合构建查询语句
def findSimiEntity(entity_type, entity):
    # 根据entity_type找到所有该类型的实体
    enttype = ""
    if entity_type == "phe":
        enttype = "FaultPhe"
    elif entity_type == "mnt":
        enttype = "FaultMnt"
    elif entity_type == "cau":
        enttype = "FaultCause"
    print("构造查询语句前合并时实体的类型enttype:" + enttype)
    # entities表示该类型的所有实体,需要通过entities[i]['n']['title']来获得实体的
    entities = db.getEntitiesByTitle(enttype)

    # print(entity_type + "类型的实体数：" + len(entities))
    # print(entities[0]['n']['title'])

    # 接下来将在所有实体中找出与识别出的实体最相似的实体
    lists = []
    for i in range(len(entities)):
        lists.append(entities[i]['n']['title'])
    # print(lists)
    res_entity = process.extractOne(entity, lists)[0]
    print("图谱中最相似实体res_entity:" + str(res_entity))
    return res_entity


# 将问题识别出来的类型和识别出来的实体进行合并,返回合并查询后的结果
def merge(question_id, res_dict):
    # 存储最终结果
    ret_dict = {}
    # 将识别出的实体解析出来 key:phe, mnt, cau
    args = ""
    args_val = ""
    for key, value in res_dict.items():
        args = key
        args_val = value

    # 搜索图谱中与args_val最相似的实体
    # 需要传入args(用来查找相应类型的实体)，args_val(用来与这个类型的所有实体做相似度对比)
    # res_entity = findSimiEntity(args, args_val)

    # Phe_has_Cause,需要传入参数phe
    if question_id == 1 and args == "phe":
        res_entity = findSimiEntity(args, args_val)
        ret_dict = getCauseByPhe(res_entity, ret_dict)
    if question_id == 2 and args == "phe":
        res_entity = findSimiEntity(args, args_val)
        ret_dict = getMntByPhe(res_entity, ret_dict)
    if question_id == 3 and args == "cau":
        res_entity = findSimiEntity(args, args_val)
        ret_dict = getPheByCause(res_entity, ret_dict)
    if question_id == 4 and args == "mnt":
        res_entity = findSimiEntity(args, args_val)
        ret_dict = getPheByMnt(res_entity, ret_dict)
    if question_id == 5 and args == "mnt":
        res_entity = findSimiEntity(args, args_val)
        ret_dict = getCauseByMnt(res_entity, ret_dict)
    elif question_id == 5:  # 当识别出问题类型，但是没有识别出这个实体类型时，则默认实体类型就是mnt型的
        res_entity = findSimiEntity("mnt", args_val)
        print("实体类型匹配失败后的结果：" + res_entity)
        ret_dict = getCauseByMnt(res_entity, ret_dict)
    return ret_dict


def question_answering(request):  # index页面需要一开始就加载的内容写在这里
    # context = {'ctx': ''}
    if request.GET:
        question = request.GET['question']
        print("提出的问题："+question)
        # 使用thulac进行中文分词
        # cut_statement = thu_lac.cut(question, text=False)
        # print(cut_statement)

        # 通过SVM对问句类型进行识别,1:phe-->cause 2:phe-->mnt 3:cause-->phe  4:mnt-->phe  5:mnt-->cause
        question_id, question_type = SVMModel.predbysvm(question)

        # 接下来将通过BILSTM-CRF进行问句中的命名实体识别 :phe, mnt, cau，识别不出实体就返回”“
        res_dict = BILSTM_CRF.resultprocess("rbfd", question, 1)
        print("BILSETM_CRF命名实体识别结果res_dict" + str(res_dict))

        # 如果识别出实体则进行下面的操作
        if res_dict != "":
            # 将识别出的实体和问句类型结合，构造查询语句
            ret_dict = merge(question_id, res_dict)
            # if ret_dict != "" and len(ret_dict) != 0 and ret_dict != 0:
            #     return render(request, 'question_answering.html', {'ret': ret_dict})
        else:
            # 如果没有识别出来，就将整个句子作为识别的实体,根据识别出的句子类型传参
            if question_id == 1 or question_id == 2:
                ret_dict = merge(question_id, dict(phe=question))
            elif question_id == 3:
                ret_dict = merge(question_id, dict(cau=question))
            else:
                ret_dict = merge(question_id, dict(mnt=question))

        if ret_dict != "" and len(ret_dict) != 0 and ret_dict != 0:
            print("返回给前端的字典："+str(ret_dict))
            return render(request, 'question_answering.html', {'ret': ret_dict})

        # ctx = {'ctx': question_type}
        ctx = {'ctx': '暂时找不到合适的答案'}
        return render(request, 'question_answering.html', ctx)

        #     if (len(zhuyu) > 0):
        #         # ret_dict = getCauseByPhe(zhuyu, ret_dict)
        #         ret_dict = getCauseByPhe("变色", ret_dict)
        # print(ret_dict)

        # if (len(ret_dict) != 0 and ret_dict != 0):
        #     return render(request, 'question_answering.html', {'ret': ret_dict})
        #
        # return render(request, 'question_answering.html', {'ctx': question_type})
    return render(request, 'question_answering.html', {'ctx': '暂时找不到答案'})
